/**
 * Copyright (c) 2011-2012
 * OmniCore CodeGuide
 */

package de.tum.in.oose.bumpers.cars;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;

/**
 * This class represents a car object.
 * 
 */
public class Car {
	private static Image defaultImage;
	
	private int maxSpeed = 10;
	private int minSpeed = 2;
	private int speed = minSpeed;
	
	private Image body;
	private Point position = new Point(5,5);
	private Dimension size = new Dimension(50,25);
	private int direction = 90;
	private boolean isCrunched;
	
	/**
	 * Constructor.
	 */
	public Car(){
		this.body = defaultImage;
		this.isCrunched = false;
	}
	
	/**
	 * Default initializer.
	 * @param maxX Maximum x value
	 * @param maxY Maximum y value
	 */
	public void initiate(int maxX, int maxY) {
		this.position.x = (int) (Math.random( ) * (maxX-getSize().width));
		this.position.y = (int) (Math.random( ) * maxY);
		if(this.position.y < getSize().height){
			this.position.y = getSize().height;
		}
		
		setDirection((int)(Math.random( ) * 360));
		int initialSpeed = (int) (Math.random( ) * maxSpeed);
		if(initialSpeed < minSpeed){
			initialSpeed = minSpeed;
		}
		this.speed = initialSpeed;
		this.isCrunched = false;
	}
	
	/**
	 * Sets Direction.
	 * @param direction new direction
	 * @throws IllegalArgumentException when not between 0 and 360.
	 */
	public void setDirection(int direction)  throws IllegalArgumentException {
		if(direction < 0 || direction > 360){
			throw new IllegalArgumentException("Direction must be between 0 and 360");
		}
		this.direction = direction;
	}
	
	/**
	 * @return direction
	 */
	public int getDirection() {
		return direction;
	}
	
	/**
	 * @return speed
	 */
	public int getSpeed(){
		return this.speed;
	}
	
	/**
	 * Increments the speed by 1.
	 */
	public void incrementSpeed(){
		if(this.speed < maxSpeed){
			this.speed++;
		}
	}
	
	/**
	 * Decrements the speed by 1.
	 */
	public void decrementSpeed(){
		if(this.speed > minSpeed){
			this.speed--;
		}
	}
	
	/**
	 * @return the body
	 */
	public Image getBody(){
		return this.body;
	}
	
	/**
	 * Set Body.
	 * @param body the body which will be set.
	 * @throws IllegalArgumentException when body is null.
	 */
	public void setBody(Image body) throws IllegalArgumentException {
		if(body == null){
			throw new IllegalArgumentException("The chassis image of a car connot be null.");
		}
		this.body = body;
	}
	
	/**
	 * @return position
	 */
	public Point getPosition(){
		return this.position;
	}
	
	/**
	 * @return size
	 */
	public Dimension getSize(){
		return this.size;
	}
	
	/**
	 * Sets crunched to TRUE.
	 */
	public final void setCrunched() {
		this.isCrunched = true;
    }
	/**
	 * @return isCrunched
	 */
    public final boolean isCrunched() {
		return isCrunched;
    }
	
	/**
	 * Algorithm for updating the position of the car.
	 * @param maxX new maximum x
	 * @param maxY new maximum y
	 */
	public synchronized void updatePosition(int maxX, int maxY) {
		if (isCrunched) {
			return;
		}
		float deltaX = speed * (float) Math.sin(Math.toRadians(direction));
		float deltaY = speed * (float) Math.cos(Math.toRadians(direction));
		
		this.position.x = this.position.x + (int)deltaX;
		this.position.y = this.position.y + (int)deltaY;
		
		if (position.x < 0) {
			position.x = 0;
			direction = 360 - direction;
		}
		
		if (position.x + size.width > maxX) {
			position.x = maxX - size.width;
			direction = 360 - direction;
		}
		if (position.y-size.height < 0) {
			position.y = size.height;
			direction = 180 - direction;
			if(direction < 0){
				direction = 360 + direction;
			}
		}
		if (position.y > maxY) {
			position.y = maxY;
			direction = 180 - direction;
			if(direction < 0){
				direction = 360 + direction;
			}
		}
    }

	/**
	 * @return the defaultImage
	 */
	public static Image getDefaultImage() {
		return defaultImage;
	}

	/**
	 * @param defaultImage the defaultImage to set
	 */
	public static void setDefaultImage(Image defaultImage) {
		Car.defaultImage = defaultImage;
	}



/**
 * @param speed the speed to set
 */
public void setSpeed(int speed) {
	this.speed = speed;
	}
/**
 * @return the maxSpeed
 */
public int getMaxSpeed() {
	return maxSpeed;
}

/**
 * @param maxSpeed the maxSpeed to set
 */
public void setMaxSpeed(int maxSpeed) {
	this.maxSpeed = maxSpeed;
}

/**
 * @return the minSpeed
 */
public int getMinSpeed() {
	return minSpeed;
}

/**
 * @param minSpeed the minSpeed to set
 */
public void setMinSpeed(int minSpeed) {
	this.minSpeed = minSpeed;
}

/**
 * @param position the position to set
 */
public void setPosition(Point position) {
	this.position = position;
}

/**
 * @param isCrunched the isCrunched to set
 */
public void setCrunched(boolean isCrunched) {
	this.isCrunched = isCrunched;
}

}

